/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package logica;

import fisica.CapaFisica;
import fisica.PacienteFisica;
import fisica.PersonaDeContactoFisica;
import fisica.TutorFisica;
import hibernate.objeto.ObraSocial;
import hibernate.objeto.Paciente;
import hibernate.objeto.Persona;
import hibernate.objeto.PersonaDeContacto;
import hibernate.objeto.Tutor;
import java.io.File;
import java.io.FileInputStream;
import java.util.Vector;
import presentacion.CapaPresentacion;
import presentacion.paciente.PacienteCarnetPresentacion;

/**
 *
 * @author Gonzalo
 */
public class PacienteLogica extends CapaLogica{

    /**
     * Agrega/modifica el paciente a la base de datos.
     *
     * @param datosPaciente El objeto paciente a agregar o modificar
     * @param paciente El paciente que se esta agregando/modificando
     * @return true si se agregó/modifica correctamente, false en caso contrario
     */
    public static boolean agregarOModificarPaciente(Object[] datosPaciente,
            Paciente paciente) {
        /*
         * Antes de crear objetos, debo saber cuales de los objetos no
         * obligatorios se deben crear
         * (Fotografia, Domicilio y Persona de Contacto)
         */
        boolean crearUsuarioWeb = false;
        if (paciente.getPersona() == null) {
            crearUsuarioWeb = true;
        }
        
        paciente = crearUObtenerObjetoPaciente(datosPaciente, paciente);
        int[] idObjetoCreado = new int[1];

        //Fotografia asociada
        if (!datosPaciente[PACIENTE_FOTO].toString().equals("")
               && datosPaciente[PACIENTE_FOTO].toString().contains("\\")) {
            String rutaAdjuntoArreglada =
                reemplazarUnaBarraInvertidaPorDosBarrasInvertidas(
                datosPaciente[PACIENTE_FOTO].toString());

            File file = new File(rutaAdjuntoArreglada);
            byte[] bFile = new byte[(int) file.length()];

            try {
                FileInputStream fileInputStream = new FileInputStream(file);
                //convert file into array of bytes
                fileInputStream.read(bFile);
                fileInputStream.close();
            } catch (Exception exc) {
                System.err.println(exc.getMessage());
            }
            //Setea el adjunto
            paciente.setNombreArchivoFotografiaPaciente(file.getName());
            paciente.setArchivoFotografiaPaciente(bFile);
        } else if (datosPaciente[PACIENTE_FOTO].toString().equals("")) { //Si no posee fotografía, se setean los datos de fotografía en null
            paciente.setNombreArchivoFotografiaPaciente(null);
            paciente.setArchivoFotografiaPaciente(null);
        }

        idObjetoCreado = new int[1];
        
        if (DomicilioLogica.agregarOModificarDomicilio(datosPaciente,
                idObjetoCreado)) {
            paciente.setDomicilio(
                    DomicilioLogica.getDomicilioPorId(
                    idObjetoCreado[0]));
            }

        if (seDebeCrearPersonaDeContacto(datosPaciente)) {
            idObjetoCreado = new int[1];
            //Vinculo la persona de contacto al paciente
            if (PersonaDeContactoLogica.agregarOModificarPersonaDeContacto(
                    datosPaciente, idObjetoCreado)) {
                paciente.setPersonaDeContacto(
                        PersonaDeContactoLogica.getPersonaDeContactoPorId(
                        idObjetoCreado[0]));
            }
        } else if (paciente != null) {
            //Si no se debe crear persona de contacto se elimina el
            //que existe, si es que existe
             if (paciente.getPersonaDeContacto() != null) {
                eliminarPersonaDeContactoAsociada(paciente);
            }
        }

        if (seDebeCrearTutor(datosPaciente)) {
            idObjetoCreado = new int[1];
            //Vinculo el tutor al paciente
            if (TutorLogica.agregarOModificarTutor(
                    datosPaciente, idObjetoCreado)) {
                paciente.setTutor(
                        TutorLogica.getTutorPorId(
                        idObjetoCreado[0]));
            }
        } else if (paciente != null) {
            //Si no se debe crear persona de contacto se elimina el
            //que existe, si es que existe
             if (paciente.getTutor() != null) {
                eliminarTutorAsociado(paciente);
            }
        }

        //Guarda/actualiza el paciente
        if (CapaFisica.guardarOActualizarObjeto(paciente)) {
            //Crea el usuario web
            if (crearUsuarioWeb) {
                    UsuarioLogica.agregarOModificarUsuarioPaciente(paciente);
            }
            return true;
        } else {
            return false;
        }
    }

    /**
     * Realiza la reasignación de los contactos al paciente.
     *
     * @param datosReasigancion Los datos de la reasignación
     * @return true si se reasignó correctamente, false en caso contrario
     */
    public static boolean reasignarContactoAPaciente(Object[][] datosReasigancion) {
        Paciente paciente;
        boolean retorno = true;
        for (int i = 0; i < datosReasigancion.length; i++) {
                paciente =
                        PacienteLogica.getPacientePorId(((Paciente) datosReasigancion[i][REASIGNACION_CONTACTO_OBJETO_PACIENTE]).getIdPaciente());
                //Persona de Contacto
                if (paciente.getPersonaDeContacto() != null && 
                        datosReasigancion[i][
                        REASIGNACION_CONTACTO_OBJETO_PERSONA_DE_CONTACTO] != null) {
                    if (!PersonaDeContactoLogica.actualizarPersonaDeContacto(
                            datosReasigancion[i])) {
                        retorno = false;
                    }
                } else if (paciente.getPersonaDeContacto() != null &&
                        datosReasigancion[i][
                        REASIGNACION_CONTACTO_OBJETO_PERSONA_DE_CONTACTO] == null) {
                    if (!eliminarPersonaDeContactoAsociada(paciente)) {
                        retorno = false;
                    }
                }

                //Tutor
                if (paciente.getTutor() != null) {
                    if (!TutorLogica.actualizarTutor(datosReasigancion[i])) {
                        retorno = false;
                    }
                }
        }
        return retorno;
    }


    /**
     * Actualiza la modificación de un paciente.
     *
     * @param pacienteAModificar El paciente a modificar
     * @return true si se actualizó correctamente, false en caso contrario
     */
    public static boolean guardarOActualizarObjeto(Paciente pacienteAModificar) {
        if (CapaFisica.guardarOActualizarObjeto(pacienteAModificar)) {
            return true;
        } else {
            return false;
        }
    }
    
    /**
     * Elimina la persona de contacto que existía.
     *
     * @param unPaciente El paciente que tenía persona de contacto
     * @return true si se eliminó correctamente, false en caso contrario
     */
    public static boolean eliminarPersonaDeContactoAsociada(Paciente unPaciente) {
        PersonaDeContacto unaPersonaDeContactoAEliminar =
                unPaciente.getPersonaDeContacto();

        Persona unaPersona = unaPersonaDeContactoAEliminar.getPersona();

        unaPersona.setPersonaDeContactos(null);
        unPaciente.setPersonaDeContacto(null);
        unaPersonaDeContactoAEliminar.setPacientes(null);
        unaPersonaDeContactoAEliminar.setPersona(null);

        //Se elimina la persona de contacto
        Vector<PersonaDeContacto> elementosAEliminar =
                new Vector<PersonaDeContacto>();
        
        elementosAEliminar.add(unaPersonaDeContactoAEliminar);

        if (CapaFisica.deleteAll(elementosAEliminar)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Elimina el tutor que existía.
     *
     * @param unPaciente El paciente que tenía tutor
     * @return true si se eliminó correctamente, false en caso contrario
     */
    public static boolean eliminarTutorAsociado(Paciente unPaciente) {
        Tutor unTutorAEliminar = unPaciente.getTutor();

        Persona unaPersona = unTutorAEliminar.getPersona();

        unaPersona.setTutors(null);
        unPaciente.setTutor(null);
        unTutorAEliminar.setPacientes(null);
        unTutorAEliminar.setPersona(null);

        //Se elimina el tutor
        Vector<Tutor> elementosAEliminar = new Vector<Tutor>();

        elementosAEliminar.add(unTutorAEliminar);
        
        if (CapaFisica.deleteAll(elementosAEliminar)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Crea un objeto paciente con los datos pasados por parámetro.
     *
     * @param datosPaciente Los datos a cargar
     * @param persona La persona que se esta agregando/modificando
     * @return El objeto Paciente recién creado
     */
    private static Paciente crearUObtenerObjetoPaciente(Object[] datosPaciente,
            Paciente paciente) {
        //Si se trata de un alta crea el objeto
        if (paciente == null) {
	    paciente = new Paciente();
        }

        //Agrega el objeto persona
        int[] idObjetoCreado = new int[1];
        Persona persona = PersonaLogica.getPersonaPorDocumentoEnBd(
                datosPaciente[PERSONA_TIPO_DE_DOCUMENTO].toString() + " " +
                datosPaciente[PERSONA_NUMERO_DE_DOCUMENTO].toString());
        PersonaLogica.agregarOModificarPersona(datosPaciente, persona,
                idObjetoCreado);

        //Vinculo la persona al paciente
        paciente.setPersona(PersonaLogica.getPersonaPorIdYEnBd(
                idObjetoCreado[0]));

        //Continúa seteando los valores adicionales para paciente
        paciente.setSexoPaciente(
                datosPaciente[PACIENTE_SEXO].toString());

        paciente.setEstadoCivilPaciente(
                datosPaciente[PACIENTE_ESTADO_CIVIL].toString());

        paciente.setOcupacionPaciente(
                datosPaciente[PACIENTE_OCUPACION].toString());

        paciente.setGrupoSanguineoPaciente(
                datosPaciente[PACIENTE_GRUPO_SANGUINEO].toString());

        paciente.setFactorSanguineoPaciente(
                datosPaciente[PACIENTE_FACTOR_SANGUINEO].toString());

        if (datosPaciente[PACIENTE_OBRA_SOCIAL] != null) {
            paciente.setObraSocial(
                    ObraSocialLogica.getObraSocialPorId(((ObraSocial)
                    datosPaciente[PACIENTE_OBRA_SOCIAL]).getIdObraSocial()));
        } else {
            paciente.setObraSocial(null);
        }

        paciente.setNumeroAfiliacionObraSocialPaciente(
                datosPaciente[PACIENTE_NUMERO_AFILIACION_OBRA_SOCIAL].toString());

        return paciente;
    }

    /**
     * Chequea si hay datos para crear el objeto PersonaDeContacto.
     *
     * @param datosPaciente Los datos del paciente a agregar
     * @return true si debe crearse el objeto, false en caso contrario
     */
    private static boolean seDebeCrearPersonaDeContacto(Object[] datosPaciente) {
        if (datosPaciente[PACIENTE_PERSONA_DE_CONTACTO] != null) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Chequea si hay datos para crear el objeto Tutor.
     *
     * @param datosPaciente Los datos del paciente a agregar
     * @return true si debe crearse el objeto, false en caso contrario
     */
    private static boolean seDebeCrearTutor(Object[] datosPaciente) {
        if (datosPaciente[PACIENTE_TUTOR] != null) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Retorna el vector de objetos Paciente cargados en la base de datos.
     *
     * @return El vector con los objetos Paciente consultado, null si no existe
     */
    public static Vector<Paciente> getVectorPaciente(){
        return PacienteFisica.getVectorPaciente();
    }

    /**
     * Retorna un objeto paciente según el número de documento.
     *
     * @param numeroDocumento El número de documento
     * @return El objeto Paciente consultado
     */
    public static Vector<Paciente> getVectorPacientePorNumeroDocumentoYEnBd(
            String numeroDocumento) {
        return PacienteFisica.getVectorPacientePorNumeroDocumentoYPorEnBd(
                numeroDocumento, true);
    }

    /**
     * Retorna un objeto paciente según su apellido.
     *
     * @param apellido El apellido del paciente
     * @return El objeto Paciente consultado
     */
    public static Vector<Paciente> getVectorPacientePorApellidoYEnBd(String apellido) {
        return PacienteFisica.getVectorPacientePorApellidoYPorEnBd(
                reemplazarUnApostrofoPorDosApostrofos(apellido), true);
    }

    /**
     * Retorna los pacientes afectados según el id de la persona involucrada.
     *
     * @param idPersona El id de la persona de contacto o tutor
     * @return El vector de objetos Paciente consultado
     */
    public static Vector<Paciente> getVectorPacientePorIdContacto(
            int idPersona){
        Vector<Paciente> pacientesTutores =
                TutorFisica.getVectorPacientePorIdPersonaDelTutor(idPersona);
        Vector<Paciente> pacientesPersonasDeContacto =
                 PersonaDeContactoFisica.
                 getVectorPacientePorIdPersonaDeLaPersonaDeContacto(idPersona);

        return mergeVectores(pacientesTutores, pacientesPersonasDeContacto);
    }

    /**
     * Retorna los pacientes afectados según el id de la obra social involucrada.
     *
     * @param idObraSocial El id de la obra social
     * @return El vector de objetos Paciente consultado
     */
    public static Vector<Paciente> getVectorPacientePorIdObraSocial(
            int idObraSocial){
        Vector<Paciente> pacientesAfectadosAObraSocial =
                ObraSocialLogica.getVectorPacientePorIdObraSocial(idObraSocial);
        return pacientesAfectadosAObraSocial;
    }

    /**
     * Retorna el objeto Paciente según el id.
     *
     * @param id El id del paciente
     * @return El objeto Paciente consultado, null si no existe
     */
    public static Paciente getPacientePorId(int id){
        return PacienteFisica.getPacientePorId(id);
    }

    /**
     * Retorna el paciente solicitado por tipo y número de documento.
     *
     * @param tipo El tipo de documento
     * @param numero El número de documento
     * @return El objeto Paciente consultado
     */
    public static Paciente getPacientePorDocumento(String tipo, String numero){
        return PacienteFisica.getPacientePorDocumento(tipo, numero);
    }

    /**
     * Retorna un objeto paciente según el tipo y número de documento.
     *
     * @param documento El tipo y número de documento
     * @return El objeto Paciente consultado
     */
    public static Paciente getPacientePorDocumento(String documento) {
        return PacienteFisica.getPacientePorDocumento(
                separarTipoDeDocumento(documento),
                separarNumeroDeDocumento(documento));
    }

    /**
     * Dado una persona, retorna el objeto paciente que lo contiene.
     *
     * @param unaPersona El objeto Persona
     * @return El objeto Paciente
     */
    public static Paciente getPacientePorPersona(Persona unaPersona) {
        return PacienteFisica.getPacientePorDocumento(
                unaPersona.getTipoDeDocumentoPersona(),
                unaPersona.getNumeroDeDocumentoPersona());
    }

    /**
     * Dada una persona verifica si es paciente, es decir si existe en la bd
     * como paciente
     *
     * @param persona La persona en cuestión
     * @return true si existe, false en caso contrario
     */
    public static boolean esPaciente(Persona persona) {
        return existePacientePorDocumento(
                persona.getTipoDeDocumentoPersona(),
                persona.getNumeroDeDocumentoPersona());
    }

    /**
     * Verifica si existe un paciente en la base de datos.
     *
     * @param tipo El tipo de documento
     * @param numero El numero de documento
     * @return true si existe, false en caso contrario
     */
    public static boolean existePacientePorDocumento(String tipo, String numero){
        Paciente paciente = PacienteFisica.getPacientePorDocumento(tipo, numero);

        return (paciente != null);
    }

    /**
     * Retorna el texto HTML correspondiente a la descripcion del paciente.
     *
     * @param paciente El paciente
     * @return El String que contiene el HTML
     */
    public static String getPacienteHTML(Paciente paciente) {
        String pacienteHTML = "";

        if (paciente != null) {
            pacienteHTML = "<font size=\"3\" face=\"arial\" color=\"blue\">PACIENTE</font><br> " +
                    "<font size=\"3\" face=\"arial\" color=\"black\">Número de HC: </font>"
                    + "<font size=\"3\" face=\"arial\">" +
                    paciente.getIdPaciente() + "</font><br>" +
                    PersonaLogica.getPersonaHTML(paciente.getPersona()) +
                    "<font size=\"3\" face=\"arial\" color=\"black\">Sexo: </font>"
                    + "<font size=\"3\" face=\"arial\">" +
                    paciente.getSexoPaciente() + "</font><br>" +
                    "<font size=\"3\" face=\"arial\" color=\"black\">Estado civil: </font>"
                    + "<font size=\"3\" face=\"arial\">" +
                    paciente.getEstadoCivilPaciente() + "</font><br>" +
                    "<font size=\"3\" face=\"arial\" color=\"black\">Ocupación: </font>"
                    + "<font size=\"3\" face=\"arial\">" +
                    paciente.getOcupacionPaciente() + "</font><br>" +
                    "<font size=\"3\" face=\"arial\" color=\"black\">Grupo sanguíneo: </font>"
                    + "<font size=\"3\" face=\"arial\">" +
                    paciente.getGrupoSanguineoPaciente() + "</font><br>" +
                    "<font size=\"3\" face=\"arial\" color=\"black\">Factor Rh: </font>"
                    + "<font size=\"3\" face=\"arial\">" +
                    paciente.getFactorSanguineoPaciente() + "</font><br>" +
                    ObraSocialLogica.getObraSocialHTML(paciente.getObraSocial()) +
                    "<font size=\"3\" face=\"arial\" color=\"black\">Número afiliación: </font>"
                    + "<font size=\"3\" face=\"arial\">" +
                    paciente.getNumeroAfiliacionObraSocialPaciente() + "</font><br>" +
                    DomicilioLogica.getDomicilioHTML(paciente.getDomicilio()) +
                    "<hr />" +
                    PersonaDeContactoLogica.getPersonaDeContactoHTML(
                    paciente.getPersonaDeContacto()) +
                    "<hr />" +
                    TutorLogica.getTutorHTML(paciente.getTutor()) +
                    "<hr />" +
                    InformacionSocialLogica.getInformacionSocialHTML(
                    paciente.getInformacionSocial()) +
                    "<hr />" +
                    FichaMortalidadLogica.getFichaMortalidadHTML(
                    paciente.getFichaMortalidad());
        }

        return pacienteHTML;
    }

    /**
     * Retorna el texto HTML correspondiente al carnet del paciente.
     *
     * @param paciente El paciente
     * @return El String que contiene el HTML del carnet
     */
    public static String getCarnetPacienteHTML(PacienteCarnetPresentacion gui) {
        String pacienteHTML = "";

        if (gui.getPaciente() != null) {
            //Ruta src(fuente del tag img HTML para visualizar imágen) de la imágen que se mostrará
            String path = 
                    CapaLogica.reemplazarUnaBarraInvertidaPorDosBarrasInvertidas(
                    CapaPresentacion.abrirArchivo(
                    gui.getPaciente().getIdPaciente(),
                    gui.getPaciente().getNombreArchivoFotografiaPaciente(),
                    gui.getPaciente().getArchivoFotografiaPaciente(),
                    false));
            if (path == null) {
                //Se recupera el archivo del directorio donde se ecuentra el jar, se normaliza el espacio
                path = new File(CapaPresentacion.class.
                        getProtectionDomain().getCodeSource().getLocation().getPath()).
                        getParent().replaceAll("%20", " ");

                if (gui.getPaciente().getSexoPaciente().equalsIgnoreCase("masculino")) {
                    path = CapaLogica.reemplazarUnaBarraInvertidaPorDosBarrasInvertidas(
                        path + "\\imagenes\\no-foto-masculino.jpg");
                } else {
                    path = CapaLogica.reemplazarUnaBarraInvertidaPorDosBarrasInvertidas(
                        path + "\\imagenes\\no-foto-femenina.jpg");
                }
            }

            path = "file:///" + path;

            //Número de hci de paciente
            String hciNumeroPaciente = String.valueOf(gui.getPaciente().getIdPaciente());

            //Apellido y nombre
            String apellidoYNombrePaciente = CapaPresentacion.
                    imprimirApellidoYNombrePersona(gui.getPaciente().getPersona());
            
            pacienteHTML =
                    "<hr /><br><table border=\"0\" align=\"center\">" +
                    "<tr> " +
                    "<td> <font size=\"10\" face=\"arial\" color=\"blue\">HCI nº: " + hciNumeroPaciente + "  " + apellidoYNombrePaciente + " </font><br><br>" +
                    "<pre><font  size=\"6\" face=\"arial\" color=\"black\">      Usuario: " + gui.getNombreDeUsuario().getText() + " </font></pre> " +
                    "<pre><font  size=\"6\" face=\"arial\" color=\"black\">      Clave: " + gui.getClaveDeUsuario().getText() + " </font><pre><br> " +
                    "<font face=\"arial\"><a href=\"\" target=\"main\">hci2010.dyndns.org</a><br /></font>" +
                    "</td> " +
                    "<td> " +
                    "<img src=\""+ path + "\" width=\"" + gui.getPanelFotografia().getWidth() + "\" height=\"" + gui.getPanelFotografia().getHeight() + "\" border=\"0\" align=\"right\"> " +
                    "</td> " +
                    "</tr> " +
                    "</table><br><hr />";
        }
        return pacienteHTML;
    }
}